package com.beta.cat.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * IP转地址或定位相关的工具类
 */
@Slf4j
public class IPLocateUtils {
    /**
     * 末尾的ip段转的long起始值，用于快速对比
     */
    private static final String KEY_START = "start";
    /**
     * 末尾的ip段转的long结束值，用于快速对比
     */
    private static final String KEY_END = "end";
    /**
     * 末尾的ip段原始值，用于快速返回
     */
    private static final String KEY_IP_START = "ipStart";
    /**
     * 末尾的ip段原始值，用于快速返回
     */
    private static final String KEY_IP_END = "ipEnd";
    /**
     * ip段格式结束ip后面的内容
     */
    private static final String KEY_IP_OTHER = "other";

    private static Pattern ipv4Pattern = Pattern.compile("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}");

    private Map<String, Object> tree = new HashMap<>();

    private IPLocateUtils() {
    }

    /**
     * 获取当前
     *
     * @return
     */
    public static IPLocateUtils getInstance() {
        return new IPLocateUtils();
    }

    /**
     * 清空IP片段库
     *
     * @return
     */
    public IPLocateUtils clearIpSegments() {
        synchronized (tree) {
            tree.clear();
            return this;
        }
    }

    /**
     * 加载指定IP片段库，将IP片段改成树状结构存储
     *
     * @param ipSegments IP片段库，每一个版本的格式是：开始IP|结束IP|....
     */
    public IPLocateUtils setIpSegments(String... ipSegments) {
        return setIpSegments(tree, ipSegments);
    }

    /**
     * 重新加载指定IP片段库，将IP片段改成树状结构存储
     *
     * @param ipSegments IP片段库，每一个版本的格式是：开始IP|结束IP|....
     */
    public IPLocateUtils reloadIpSegments(String... ipSegments) {
        Map<String, Object> newTree = new HashMap<>();
        setIpSegments(newTree, ipSegments);
        synchronized (tree) {
            tree.clear();
            tree.putAll(newTree);
            return this;
        }
    }

    /**
     * 加载指定IP片段库，将IP片段改成树状结构存储
     *
     * @param ipSegments IP片段库，每一个版本的格式是：开始IP|结束IP|....
     */
    private IPLocateUtils setIpSegments(Map<String, Object> tree, String... ipSegments) {
        if (ipSegments == null || ipSegments.length < 1) {
            return this;
        }
        synchronized (tree) {
            for (String ipSegment : ipSegments) {
                if (StringUtils.isBlank(ipSegment)) {
                    continue;
                }
                String[] segments = ipSegment.trim().split("\\|", 3);//最多分割成3段
                if (segments.length < 2) {
                    continue;//如果长度不够，说明格式不正确，不处理
                }
                String ipStart = segments[0].trim();
                String ipEnd = segments[1].trim();
                String other = segments.length > 2 ? segments[2] : null;

                if (!ipv4Pattern.matcher(ipStart).matches() || !ipv4Pattern.matcher(ipEnd).matches()) {
                    continue;//如果IP地址不合法，则不处理
                }

                String[] ipStarts = ipStart.split("\\.");
                String[] ipEnds = ipEnd.split("\\.");
                Map<String, Object> subTree = tree;
                for (int i = 0; i < ipStarts.length; i++) {
                    String ipS = ipStarts[i];
                    String ipE = ipEnds[i];
                    if (ipS.equals(ipE)) {//相同，说明可以归并
                        Map tmp = (Map) subTree.get(ipS);
                        if (tmp == null) {
                            tmp = new HashMap();
                        }
                        if (i == ipStarts.length - 1) {//最后一个也相同
                            setTailInfo(other, ipStarts, ipEnds, subTree, i);
                        }
                        subTree.put(ipS, tmp);
                        subTree = tmp;
                        continue;
                    } else {//不相同，则记录开始段与结束段信息。
                        setTailInfo(other, ipStarts, ipEnds, subTree, i);
                        break;//遇到不一样的就跳出了
                    }
                }
            }
            return this;
        }
    }

    private void setTailInfo(String other, String[] ipStarts, String[] ipEnds, Map<String, Object> subTree, int i) {
        String subIpS = concatIp(ipStarts, i);
        String subIpE = concatIp(ipEnds, i);
        List<String> ipSts = (List<String>) subTree.get(KEY_IP_START);
        List<String> ipEds = (List<String>) subTree.get(KEY_IP_END);
        List<Long> sts = (List<Long>) subTree.get(KEY_START);
        List<Long> eds = (List<Long>) subTree.get(KEY_END);
        List<String> others = (List<String>) subTree.get(KEY_IP_OTHER);

        if (ipSts == null) {
            ipSts = new ArrayList<>();
        }
        ipSts.add(subIpS);

        if (ipEds == null) {
            ipEds = new ArrayList<>();
        }
        ipEds.add(subIpE);

        if (sts == null) {
            sts = new ArrayList<>();
        }
        sts.add(ipToLong(subIpS));

        if (eds == null) {
            eds = new ArrayList<>();
        }
        eds.add(ipToLong(subIpE));

        if (others == null) {
            others = new ArrayList<>();
        }
        others.add(other);

        subTree.put(KEY_IP_START, ipSts);
        subTree.put(KEY_IP_END, ipEds);
        subTree.put(KEY_START, sts);
        subTree.put(KEY_END, eds);
        subTree.put(KEY_IP_OTHER, others);
    }

    /**
     * 判断指定的ip在不在当前的ip库范围内
     *
     * @param ip 指定的ip
     * @return true-在指定的范围; false-不在
     */
    public boolean isInRange(String ip) {
        return StringUtils.isNotBlank(matchRange(ip));
    }

    /**
     * 匹配出指定的ip所属的ip段
     *
     * @param ip 指定的ip
     * @return 指定的ip范围段，返回格式与入库前的保持一致。
     */
    public String matchRange(String ip) {
        if (StringUtils.isBlank(ip) || tree.isEmpty()) {
            return "";
        }
        ip = StringUtils.trim(ip);
        if (!ipv4Pattern.matcher(ip).matches()) {
            return "";//不是IP，则不处理
        }
        //一节节地取
        return doMatch(ip);
    }

    private String doMatch(String ip) {
        String[] segs = ip.split("\\.");
        Map<String, Object> subTree = tree;
        StringBuilder pre = new StringBuilder();
        for (int i = 0; i < segs.length; i++) {
            String seg = segs[i];

            Map tmp = (Map) subTree.get(seg);
            if (tmp == null) {//不存在了，则直接取当前树里面的范围
                return match(subTree, ip, pre);
            } else {//存在，则继续入下找
                subTree = tmp;
                if (pre.length() > 0) {
                    pre.append(".");
                }
                pre.append(seg);
                //要先看一下这里面在不在这里面的范围
                String ret = match(subTree, ip, pre);
                if (StringUtils.isNotBlank(ret)) return ret;
                continue;
            }
        }
        return "";
    }

    private String match(Map<String, Object> subTree, String ip, StringBuilder pre) {
        List<Long> starts = (List<Long>) subTree.get(KEY_START);
        List<Long> ends = (List<Long>) subTree.get(KEY_END);
        if (!CollectionUtils.isEmpty(starts) && !CollectionUtils.isEmpty(ends)) {
            long val = ipToLong(ip.substring(pre.length() + 1));//把前端的内容及点去掉

            for (int j = 0; j < starts.size(); j++) {
                long start = starts.get(j);
                long end = ends.get(j);
                if (val >= start && val <= end) {//在范围内
                    String other = ((List<String>) subTree.get(KEY_IP_OTHER)).get(j);

                    return pre + "." + ((List<String>) subTree.get(KEY_IP_START)).get(j) + "|"
                            + pre + "." + ((List<String>) subTree.get(KEY_IP_END)).get(j)
                            + (other == null ? "" : ("|" + other));
                }
            }
        }
        return "";
    }


    private long ipToLong(String subIp) {
        String[] ss = subIp.split("\\.");
        long ret = 0;
        for (int i = 0; i < ss.length; i++) {
            long tmp = Long.parseLong(ss[i]);
            tmp = tmp << (8 * (ss.length - i - 1));
            ret += tmp;
        }
        return ret;
    }

    private String concatIp(String[] ipSegments, int i) {
        StringBuilder ret = new StringBuilder();
        for (int j = i; j < ipSegments.length; j++) {
            if (ret.length() > 0) {
                ret.append(".");
            }
            ret.append(ipSegments[j]);
        }
        return ret.toString();
    }

    /**
     * 正确性验算
     *
     * @param args
     */
    public static void main(String[] args) {
        String ipSegments = "14.16.137.0|14.16.137.255|中国|广东省|东莞市|电信,14.17.64.0|14.17.95.255|中国|广东省|东莞市|电信,14.18.232.0|14.18.233.255|中国|广东省|东莞市|电信,14.22.12.0|14.22.15.255|1024|||,14.24.91.0|14.24.91.255|256|||,14.24.111.128|14.24.127.255|中国|广东省|东莞市|电信,14.25.32.0|14.25.37.255|1536|||,14.25.56.0|14.25.57.255|512|||,14.25.64.0|14.25.67.255|1024|||,14.25.80.0|14.25.95.255|4096|||,14.30.72.0|14.30.72.255|256|||,14.31.64.0|14.31.71.255|中国|广东省|东莞市|电信,14.119.0.0|14.119.63.255|中国|广东省|东莞市|电信,14.120.0.0|14.120.159.255|中国|广东省|东莞市|电信,14.150.128.0|14.150.191.255|中国|广东省|东莞市|电信,14.152.80.0|14.152.103.255|中国|广东省|东莞市|电信,14.154.64.0|14.154.127.255|中国|广东省|东莞市|电信,14.156.0.0|14.156.255.255|中国|广东省|东莞市|电信,14.215.196.0|14.215.207.255|中国|广东省|东莞市|电信,14.215.212.0|14.215.215.255|中国|广东省|东莞市|电信,14.215.240.0|14.215.243.255|中国|广东省|东莞市|电信,14.215.248.0|14.222.255.255|中国|广东省|东莞市|电信,27.37.0.0|27.37.255.255|中国|广东省|东莞市|联通,27.39.72.0|27.39.75.255|中国|广东省|东莞市|联通,27.39.88.0|27.39.95.255|中国|广东省|东莞市|联通,27.39.216.0|27.39.223.255|中国|广东省|东莞市|联通,27.40.24.0|27.40.25.255|中国|广东省|东莞市|联通,27.44.0.0|27.44.255.255|中国|广东省|东莞市|联通,36.193.52.0|36.193.55.255|中国|广东省|东莞市|铁通,39.134.42.0|39.134.42.255|256|||,39.134.44.0|39.134.44.255|256|||,39.134.46.0|39.134.47.255|512|||,39.135.58.0|39.135.58.255|256|||,39.137.28.0|39.137.28.255|256|||,39.137.30.0|39.137.30.255|256|||,39.137.32.0|39.137.33.255|512|||,42.157.128.0|42.157.135.255|中国|广东省|东莞市|电信,42.157.192.0|42.157.199.255|中国|广东省|东莞市|电信,42.247.33.144|42.247.33.159|中国|广东省|东莞市|教育网,42.247.45.112|42.247.45.127|中国|广东省|东莞市|教育网,42.247.49.192|42.247.49.223|中国|广东省|东莞市|教育网,43.236.44.0|43.236.51.255|中国|广东省|东莞市|0,43.238.108.0|43.238.111.255|中国|广东省|东莞市|0,43.247.68.0|43.247.71.255|中国|广东省|东莞市|电信,45.126.116.0|45.126.119.255|中国|广东省|东莞市|0,45.249.212.0|45.249.215.255|中国|广东省|东莞市|电信,49.221.136.0|49.221.141.255|中国|广东省|东莞市|鹏博士,58.252.0.0|58.252.63.255|中国|广东省|东莞市|联通,58.253.80.0|58.253.111.255|中国|广东省|东莞市|联通,58.254.200.0|58.254.203.255|中国|广东省|东莞市|联通,58.255.32.0|58.255.95.255|中国|广东省|东莞市|联通,59.36.0.0|59.36.31.255|中国|广东省|东莞市|电信,59.36.96.0|59.36.103.255|中国|广东省|东莞市|电信,59.36.107.0|59.36.108.255|中国|广东省|东莞市|电信,59.36.176.0|59.36.191.255|中国|广东省|东莞市|电信,59.37.16.0|59.37.23.255|中国|广东省|东莞市|电信,59.37.176.0|59.37.176.255|中国|广东省|东莞市|电信,59.37.178.0|59.37.179.255|中国|广东省|东莞市|电信,59.37.196.0|59.37.198.255|中国|广东省|东莞市|电信,59.37.200.0|59.37.207.255|中国|广东省|东莞市|电信,59.38.96.0|59.38.103.255|中国|广东省|东莞市|电信,59.38.112.0|59.38.119.255|中国|广东省|东莞市|电信,59.39.152.0|59.39.255.255|中国|广东省|东莞市|电信,61.142.0.0|61.142.39.255|中国|广东省|东莞市|电信,61.142.44.0|61.142.63.255|中国|广东省|东莞市|电信,61.145.160.0|61.145.162.255|中国|广东省|东莞市|电信,61.145.168.0|61.145.223.255|中国|广东省|东莞市|电信,61.235.120.0|61.235.125.255|中国|广东省|东莞市|铁通,61.242.24.0|61.242.31.255|中国|广东省|东莞市|联通,101.106.64.0|101.106.95.255|中国|广东省|东莞市|鹏博士,101.126.0.0|101.126.63.255|中国|广东省|东莞市|鹏博士,101.130.128.0|101.130.191.255|中国|广东省|东莞市|鹏博士,101.130.224.0|101.130.255.255|中国|广东省|东莞市|鹏博士,101.246.0.0|101.246.63.255|中国|广东省|东莞市|鹏博士,101.247.192.0|101.247.255.255|中国|广东省|东莞市|鹏博士,103.5.52.0|103.5.52.255|中国|广东省|东莞市|电信,103.32.44.0|103.32.51.255|中国|广东省|东莞市|0,103.34.108.0|103.34.111.255|中国|广东省|东莞市|0,103.45.0.0|103.45.63.255|中国|广东省|东莞市|电信,103.79.243.0|103.79.243.255|256|||,103.212.84.0|103.212.87.255|中国|广东省|东莞市|0,103.218.216.0|103.218.219.255|中国|广东省|东莞市|电信,110.64.176.0|110.64.199.255|中国|广东省|东莞市|教育网,110.64.204.0|110.64.205.255|中国|广东省|东莞市|教育网,110.120.112.0|110.120.119.255|中国|广东省|东莞市|铁通,110.208.12.0|110.208.19.255|中国|广东省|东莞市|铁通,110.208.120.0|110.208.127.255|中国|广东省|东莞市|铁通,110.208.144.0|110.208.151.255|中国|广东省|东莞市|铁通,110.208.184.0|110.208.187.255|中国|广东省|东莞市|铁通,110.209.164.0|110.209.171.255|中国|广东省|东莞市|铁通,110.209.248.0|110.209.251.255|中国|广东省|东莞市|铁通,110.210.64.0|110.210.79.255|中国|广东省|东莞市|铁通,110.211.0.0|110.211.31.255|中国|广东省|东莞市|铁通,110.211.208.0|110.211.223.255|中国|广东省|东莞市|铁通,111.148.8.0|111.148.15.255|中国|广东省|东莞市|铁通,111.148.216.0|111.148.219.255|中国|广东省|东莞市|铁通,111.151.0.0|111.151.15.255|中国|广东省|东莞市|铁通,111.151.72.0|111.151.75.255|中国|广东省|东莞市|铁通,111.151.88.0|111.151.103.255|中国|广东省|东莞市|铁通,112.89.36.0|112.89.38.255|768|||,112.89.108.0|112.89.110.255|中国|广东省|东莞市|联通,112.90.88.0|112.90.95.255|中国|广东省|东莞市|联通,112.90.216.0|112.90.223.255|中国|广东省|东莞市|联通,112.91.33.0|112.91.33.255|中国|广东省|东莞市|联通,112.91.88.0|112.91.95.255|中国|广东省|东莞市|联通,112.91.216.0|112.91.223.255|中国|广东省|东莞市|联通,112.92.11.0|112.92.11.255|256|||,112.93.128.0|112.93.255.255|中国|广东省|东莞市|联通,112.96.8.0|112.96.8.255|256|||,112.97.160.0|112.97.183.255|中国|广东省|东莞市|联通,112.97.196.0|112.97.197.255|512|||,112.97.200.0|112.97.235.255|中国|广东省|东莞市|联通,112.97.240.0|112.97.255.255|中国|广东省|东莞市|联通,113.64.236.0|113.64.239.255|中国|广东省|东莞市|电信,113.77.0.0|113.80.255.255|中国|广东省|东莞市|电信,113.96.254.0|113.96.254.255|中国|广东省|东莞市|电信,113.98.0.0|113.98.53.255|中国|广东省|东莞市|电信,113.98.188.0|113.98.188.255|中国|广东省|东莞市|电信,113.98.190.0|113.98.191.255|中国|广东省|东莞市|电信,113.99.128.0|113.99.135.255|中国|广东省|东莞市|电信,113.99.144.0|113.99.191.255|中国|广东省|东莞市|电信,113.100.128.0|113.100.135.255|中国|广东省|东莞市|电信,113.100.144.0|113.100.159.255|中国|广东省|东莞市|电信,113.102.192.0|113.102.255.255|中国|广东省|东莞市|电信,113.104.20.0|113.104.31.255|3072|||,113.105.128.0|113.105.191.255|中国|广东省|东莞市|电信,113.108.126.0|113.108.127.255|中国|广东省|东莞市|电信,113.108.240.0|113.108.255.255|中国|广东省|东莞市|电信,113.113.112.0|113.113.119.255|中国|广东省|东莞市|电信,113.115.136.0|113.115.136.255|256|||,113.115.138.0|113.115.138.255|256|||,115.173.32.0|115.173.63.255|中国|广东省|东莞市|鹏博士,116.4.0.0|116.4.255.255|中国|广东省|东莞市|电信,116.6.14.0|116.6.17.255|中国|广东省|东莞市|电信,116.6.28.0|116.6.29.255|中国|广东省|东莞市|电信,116.6.44.0|116.6.47.255|中国|广东省|东莞市|电信,116.6.76.0|116.6.79.255|中国|广东省|东莞市|电信,116.6.82.0|116.6.87.255|中国|广东省|东莞市|电信,116.6.92.0|116.6.95.255|中国|广东省|东莞市|电信,116.6.132.0|116.6.139.255|中国|广东省|东莞市|电信,116.6.202.0|116.6.203.255|512|||,116.6.208.0|116.6.211.255|中国|广东省|东莞市|电信,116.6.240.0|116.6.243.255|中国|广东省|东莞市|电信,116.18.0.0|116.18.255.255|中国|广东省|东莞市|电信,116.56.208.0|116.56.209.255|中国|广东省|东莞市|教育网,116.204.192.0|116.204.195.255|中国|广东省|东莞市|电信,116.204.232.0|116.204.235.255|1024|||,116.204.244.0|116.204.247.255|1024|||,117.49.2.0|117.49.2.255|中国|广东省|东莞市|阿里巴巴,117.49.5.0|117.49.5.255|中国|广东省|东莞市|阿里巴巴,117.136.32.0|117.136.32.147|中国|广东省|东莞市|移动,117.136.33.40|117.136.33.127|中国|广东省|东莞市|移动,117.136.39.224|117.136.39.239|中国|广东省|东莞市|移动,117.136.40.32|117.136.40.47|中国|广东省|东莞市|移动,117.136.41.8|117.136.41.15|中国|广东省|东莞市|移动,117.142.76.0|117.142.76.255|256|||,117.142.78.0|117.142.78.31|中国|广东省|东莞市|移动,119.121.33.0|119.121.43.255|中国|广东省|东莞市|电信,119.127.64.0|119.128.255.255|中国|广东省|东莞市|电信,119.140.0.0|119.140.31.255|中国|广东省|东莞市|电信,119.141.0.0|119.141.255.255|中国|广东省|东莞市|电信,119.144.0.0|119.144.255.255|中国|广东省|东莞市|电信,119.145.96.0|119.145.127.255|中国|广东省|东莞市|电信,119.147.96.0|119.147.135.255|中国|广东省|东莞市|电信,119.147.144.0|119.147.159.255|中国|广东省|东莞市|电信,119.252.251.0|119.252.253.255|中国|广东省|东莞市|0,120.80.72.0|120.80.75.255|1024|||,120.80.148.0|120.80.155.255|中国|广东省|东莞市|联通,120.80.236.0|120.80.239.255|中国|广东省|东莞市|联通,120.83.0.230|120.83.0.230|中国|广东省|东莞市|联通,120.83.10.0|120.83.10.255|中国|广东省|东莞市|联通,120.84.0.48|120.84.0.51|中国|广东省|东莞市|联通,120.84.0.128|120.84.0.191|中国|广东省|东莞市|联通,120.84.64.0|120.84.65.255|中国|广东省|东莞市|联通,120.84.128.0|120.84.255.255|中国|广东省|东莞市|联通,120.86.0.148|120.86.0.163|中国|广东省|东莞市|联通,120.86.0.204|120.86.0.219|中国|广东省|东莞市|联通,120.86.64.0|120.86.191.255|中国|广东省|东莞市|联通,120.196.1.0|120.196.1.255|中国|广东省|东莞市|移动,120.196.6.0|120.196.7.255|中国|广东省|东莞市|移动,120.196.29.0|120.196.29.255|中国|广东省|东莞市|移动,120.196.128.0|120.196.130.255|中国|广东省|东莞市|移动,120.196.148.0|120.196.161.255|中国|广东省|东莞市|移动,120.196.175.0|120.196.175.255|中国|广东省|东莞市|移动,120.196.242.0|120.196.242.15|中国|广东省|东莞市|移动,120.196.242.112|120.196.242.167|中国|广东省|东莞市|移动,120.196.253.16|120.196.253.87|中国|广东省|东莞市|移动,120.197.139.0|120.197.190.255|中国|广东省|东莞市|移动,120.197.194.0|120.197.198.255|中国|广东省|东莞市|移动,120.197.200.0|120.197.203.255|中国|广东省|东莞市|移动,120.198.157.0|120.198.157.255|256|||,120.198.174.0|120.198.174.255|中国|广东省|东莞市|移动,120.198.190.0|120.198.190.255|中国|广东省|东莞市|移动,120.198.224.128|120.198.224.213|中国|广东省|东莞市|移动,120.198.232.0|120.198.232.255|中国|广东省|东莞市|移动,120.198.248.176|120.198.248.191|中国|广东省|东莞市|移动,120.229.103.0|120.229.152.255|中国|广东省|东莞市|移动,120.233.44.0|120.233.44.255|256|||,120.233.76.0|120.233.78.255|768|||,120.234.128.0|120.234.143.255|中国|广东省|东莞市|移动,120.234.160.0|120.234.163.255|中国|广东省|东莞市|移动,120.234.204.0|120.234.204.255|256|||,120.235.0.0|120.235.75.255|中国|广东省|东莞市|移动,120.236.64.0|120.236.119.255|中国|广东省|东莞市|移动,120.238.137.0|120.238.143.255|1792|||,120.238.168.0|120.238.175.255|中国|广东省|东莞市|移动,120.240.1.0|120.240.1.255|中国|广东省|东莞市|移动,120.240.16.0|120.240.16.255|256|||,120.240.18.0|120.240.18.255|256|||,120.241.49.0|120.241.49.255|256|||,121.10.0.0|121.10.23.255|中国|广东省|东莞市|电信,121.12.104.0|121.12.175.255|中国|广东省|东莞市|电信,121.13.0.0|121.13.255.255|中国|广东省|东莞市|电信,121.14.128.0|121.14.159.255|中国|广东省|东莞市|电信,122.13.156.0|122.13.156.255|中国|广东省|东莞市|联通,122.13.159.0|122.13.167.255|中国|广东省|东莞市|联通,122.13.180.0|122.13.180.255|中国|广东省|东莞市|联通,122.72.92.0|122.72.92.255|中国|广东省|东莞市|铁通,123.64.32.0|123.64.39.255|中国|广东省|东莞市|铁通,123.64.48.0|123.64.63.255|中国|广东省|东莞市|铁通,123.65.240.0|123.65.255.255|中国|广东省|东莞市|铁通,123.66.64.0|123.66.64.255|中国|广东省|东莞市|铁通,123.88.136.0|123.88.143.255|中国|广东省|东莞市|铁通,123.88.176.0|123.88.191.255|中国|广东省|东莞市|铁通,123.89.64.0|123.89.71.255|中国|广东省|东莞市|铁通,123.89.144.0|123.89.159.255|中国|广东省|东莞市|铁通,124.172.178.0|124.172.178.255|中国|广东省|东莞市|鹏博士,124.248.64.0|124.248.127.255|16384|||,125.88.4.0|125.88.5.255|中国|广东省|东莞市|电信,125.88.14.0|125.88.14.255|中国|广东省|东莞市|电信,125.88.160.0|125.88.167.255|中国|广东省|东莞市|电信,125.93.64.0|125.94.31.255|中国|广东省|东莞市|电信,139.5.192.0|139.5.195.255|中国|广东省|东莞市|0,157.61.32.0|157.61.33.255|中国|广东省|东莞市|联通,157.61.216.0|157.61.223.255|中国|广东省|东莞市|联通,157.122.216.0|157.122.223.255|中国|广东省|东莞市|联通,157.156.0.0|157.156.127.255|中国|广东省|东莞市|联通,157.255.120.0|157.255.159.255|中国|广东省|东莞市|联通,163.142.0.0|163.142.127.255|中国|广东省|东莞市|联通,163.177.216.0|163.177.223.255|中国|广东省|东莞市|联通,180.89.128.0|180.89.159.255|中国|广东省|东莞市|鹏博士,183.2.192.0|183.2.207.255|中国|广东省|东莞市|电信,183.6.224.0|183.6.239.255|中国|广东省|东莞市|电信,183.22.0.0|183.23.255.255|中国|广东省|东莞市|电信,183.42.28.0|183.42.29.255|512|||,183.42.37.0|183.42.37.255|中国|广东省|东莞市|电信,183.43.15.0|183.43.15.255|256|||,183.43.196.0|183.43.196.255|256|||,183.43.224.0|183.43.231.255|中国|广东省|东莞市|电信,183.47.60.0|183.47.60.255|中国|广东省|东莞市|电信,183.49.128.0|183.49.255.255|中国|广东省|东莞市|电信,183.53.64.0|183.53.127.255|中国|广东省|东莞市|电信,183.57.56.0|183.57.56.255|中国|广东省|东莞市|电信,183.57.192.0|183.57.255.255|中国|广东省|东莞市|电信,183.58.104.0|183.58.107.255|中国|广东省|东莞市|电信,183.59.32.0|183.59.39.255|中国|广东省|东莞市|电信,183.59.69.0|183.59.69.255|中国|广东省|东莞市|电信,183.59.168.0|183.59.175.255|中国|广东省|东莞市|电信,183.60.128.0|183.60.175.255|中国|广东省|东莞市|电信,183.60.224.0|183.60.231.255|中国|广东省|东莞市|电信,183.61.160.0|183.61.191.255|中国|广东省|东莞市|电信,183.61.220.128|183.61.220.135|中国|广东省|东莞市|电信,183.61.224.0|183.61.255.255|中国|广东省|东莞市|电信,183.63.192.0|183.63.229.255|中国|广东省|东莞市|电信,183.232.211.0|183.232.211.255|256|||,183.232.238.128|183.232.239.255|中国|广东省|东莞市|移动,183.233.2.0|183.233.4.255|中国|广东省|东莞市|移动,183.233.20.0|183.233.20.255|中国|广东省|东莞市|移动,183.233.29.0|183.233.30.255|中国|广东省|东莞市|移动,183.233.216.0|183.233.223.255|中国|广东省|东莞市|移动,183.234.0.0|183.234.7.255|中国|广东省|东莞市|移动,183.234.80.0|183.234.95.255|中国|广东省|东莞市|移动,183.234.212.0|183.234.223.255|中国|广东省|东莞市|移动,183.235.24.0|183.235.24.255|中国|广东省|东莞市|移动,183.235.63.0|183.235.67.255|中国|广东省|东莞市|移动,183.235.69.0|183.235.69.31|中国|广东省|东莞市|移动,183.235.151.0|183.235.154.255|中国|广东省|东莞市|移动,183.235.159.0|183.235.159.255|中国|广东省|东莞市|移动,183.235.162.0|183.235.162.255|中国|广东省|东莞市|移动,183.235.166.0|183.235.166.255|256|||,183.237.80.0|183.237.81.255|中国|广东省|东莞市|移动,183.237.208.0|183.237.223.255|中国|广东省|东莞市|移动,183.238.32.0|183.238.39.255|中国|广东省|东莞市|移动,183.238.128.0|183.238.139.255|中国|广东省|东莞市|移动,183.238.160.0|183.238.171.255|中国|广东省|东莞市|移动,183.239.180.0|183.239.191.255|中国|广东省|东莞市|移动,183.240.90.0|183.240.91.255|512|||,183.240.192.0|183.240.192.255|中国|广东省|东莞市|移动,202.38.129.240|202.38.129.255|中国|广东省|东莞市|科技网,202.96.146.0|202.96.147.255|中国|广东省|东莞市|电信,202.96.172.0|202.96.173.255|中国|广东省|东莞市|电信,202.96.175.0|202.96.176.255|中国|广东省|东莞市|电信,202.103.164.0|202.103.165.255|中国|广东省|东莞市|电信,202.103.183.0|202.103.183.255|中国|广东省|东莞市|电信,202.103.187.0|202.103.187.255|中国|广东省|东莞市|电信,202.104.160.0|202.104.183.255|中国|广东省|东莞市|电信,202.105.192.0|202.105.211.255|中国|广东省|东莞市|电信,202.173.224.0|202.173.255.255|中国|广东省|东莞市|电信,202.192.111.0|202.192.112.255|512|||,202.192.192.0|202.192.223.255|中国|广东省|东莞市|教育网,203.93.197.0|203.93.197.255|中国|广东省|东莞市|联通,210.14.248.0|210.14.248.255|中国|广东省|东莞市|联通,210.39.120.0|210.39.123.255|中国|广东省|东莞市|教育网,210.39.232.0|210.39.239.255|中国|广东省|东莞市|教育网,211.97.56.0|211.97.56.255|中国|广东省|东莞市|联通,211.99.96.0|211.99.111.255|中国|广东省|东莞市|电信,211.102.80.0|211.102.95.255|中国|广东省|东莞市|电信,211.136.214.0|211.136.214.255|256|||,211.136.216.0|211.136.216.255|中国|广东省|东莞市|移动,211.136.229.0|211.136.229.255|256|||,211.139.128.0|211.139.128.255|中国|广东省|东莞市|移动,211.139.132.34|211.139.132.34|中国|广东省|东莞市|移动,211.139.132.36|211.139.132.36|中国|广东省|东莞市|移动,211.139.153.0|211.139.153.255|中国|广东省|东莞市|移动,211.139.192.0|211.139.195.255|中国|广东省|东莞市|移动,211.139.198.0|211.139.199.255|中国|广东省|东莞市|移动,211.148.128.0|211.148.159.255|中国|广东省|东莞市|电信,211.161.76.0|211.161.77.255|中国|广东省|东莞市|鹏博士,211.162.96.0|211.162.103.255|中国|广东省|东莞市|鹏博士,218.16.0.0|218.16.127.255|中国|广东省|东莞市|电信,218.104.184.0|218.104.191.255|中国|广东省|东莞市|联通,218.204.160.0|218.204.167.255|中国|广东省|东莞市|移动,218.247.32.0|218.247.63.255|中国|广东省|东莞市|联通,219.130.0.0|219.130.127.255|中国|广东省|东莞市|电信,219.132.200.0|219.132.255.255|中国|广东省|东莞市|电信,219.222.160.0|219.222.191.255|中国|广东省|东莞市|教育网,220.198.64.0|220.198.127.255|中国|广东省|东莞市|联通,221.4.1.128|221.4.1.129|中国|广东省|东莞市|联通,221.4.16.0|221.4.19.255|中国|广东省|东莞市|联通,221.4.128.0|221.4.143.255|中国|广东省|东莞市|联通,221.172.80.0|221.172.87.255|中国|广东省|东莞市|铁通,221.172.116.0|221.172.135.255|中国|广东省|东莞市|铁通,221.177.82.128|221.177.82.255|中国|广东省|东莞市|移动,221.177.95.0|221.177.95.255|中国|广东省|东莞市|移动,221.179.25.0|221.179.31.255|中国|广东省|东莞市|移动,221.179.60.0|221.179.60.255|中国|广东省|东莞市|移动,222.50.40.0|222.50.47.255|中国|广东省|东莞市|铁通,222.50.80.0|222.50.87.255|中国|广东省|东莞市|铁通,222.50.248.0|222.50.255.255|中国|广东省|东莞市|铁通,223.73.28.0|223.73.35.255|中国|广东省|东莞市|移动,223.73.125.0|223.73.130.255|中国|广东省|东莞市|移动,223.73.188.0|223.73.191.255|中国|广东省|东莞市|移动,223.73.202.0|223.73.205.255|中国|广东省|东莞市|移动,223.73.214.0|223.73.215.255|中国|广东省|东莞市|移动,223.73.220.0|223.73.220.255|中国|广东省|东莞市|移动,223.74.6.0|223.74.9.255|中国|广东省|东莞市|移动,223.74.17.0|223.74.20.255|1024|||,223.74.36.0|223.74.39.255|中国|广东省|东莞市|移动,223.74.109.0|223.74.122.255|中国|广东省|东莞市|移动,223.74.159.0|223.74.187.255|中国|广东省|东莞市|移动,223.104.1.128|223.104.1.167|中国|广东省|东莞市|移动,223.104.61.0|223.104.61.127|中国|广东省|东莞市|移动,223.104.63.200|223.104.64.255|中国|广东省|东莞市|移动,223.104.65.72|223.104.79.255|中国|广东省|东莞市|移动,223.210.96.0|223.210.127.255|中国|广东省|东莞市|鹏博士";
        IPLocateUtils ipLocateUtils = IPLocateUtils.getInstance().setIpSegments(ipSegments.split(","));

        long start = System.currentTimeMillis();
        for (String ipSeg : ipSegments.split(",")) {
            String[] segments = ipSeg.trim().split("\\|", 3);//最多分割成3段
            if (segments.length < 2) {
                continue;//如果长度不够，说明格式不正确，不处理
            }
            String ipStart = segments[0].trim();
            String ipEnd = segments[1].trim();
            String lastStart = ipStart.substring(ipStart.lastIndexOf(".") + 1);
            String lastEnd = ipEnd.substring(ipEnd.lastIndexOf(".") + 1);
            String[] ips = {ipStart, ipEnd, ipStart.substring(0, ipStart.lastIndexOf(".") + 1) + RandomUtils.nextInt(Integer.parseInt(lastStart), Integer.parseInt(lastEnd))};
            for (String ip : ips) {
                String ret = ipLocateUtils.matchRange(ip);
                if (!ipSeg.equals(ret)) {
                    System.err.println("查找结果对比不正确！" + ip + ";" + ipSeg + ";" + ret);
                }
            }
        }
        System.out.println("对比结束，耗时：" + (System.currentTimeMillis() - start) + "ms");
    }

}
